package com.eonmind.pay.entity;

import com.eonmind.common.provider.entity.pay.Order;
import com.eonmind.pay.config.WxPayConfig;
import com.eonmind.pay.enums.TradeState;
import com.eonmind.pay.enums.WxApiEnum;
import com.eonmind.pay.enums.WxNotifyType;
import com.eonmind.pay.utils.HttpUtils;
import com.eonmind.pay.utils.WechatPay2ValidatorForRequest;
import com.google.gson.Gson;
import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;
import com.wechat.pay.contrib.apache.httpclient.util.AesUtil;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.util.HashMap;
import java.util.Map;

/**
 * @ClassName WxChatPay
 * @Description TODO
 * Author 32004
 * Date 2025/5/13 15:43
 * Version 1.0
 **/

@Slf4j
@Component
public class WxChatPay implements Payment{

  ;
    @Resource
    WxPayConfig wxPayConfig;

    @Resource
    private CloseableHttpClient httpClient;

    @Resource
    Verifier verifier;

    @Override
    public String pay(Order order) throws IOException {

        log.info("调用统一下单API");

        //调用统一下单API
        HttpPost httpPost = new HttpPost(wxPayConfig.getDomain().concat(WxApiEnum.TRANSACTION_API.getUrl()));
        // 请求body参数
        Gson gson = new Gson();
        Map paramsmap = new HashMap<>();
        paramsmap.put("appid", wxPayConfig.getAppId());
        paramsmap.put("mchid",wxPayConfig.getMchId());
        paramsmap.put("out_trade_no",order.getId().toString());
        paramsmap.put("notify_url",wxPayConfig.getNotifyDomain());
        paramsmap.put("description",order.getDescription());
        Map amountMap = new HashMap<>();
//        amountMap.put("total",order.getAmount());
        amountMap.put("total",10);
        amountMap.put("currency", "CNY");

        paramsmap.put("amount",amountMap);

        //将参数转换为json格式字符串
        String jsonParams = gson.toJson(paramsmap);

        StringEntity entity = new StringEntity(jsonParams,"utf-8");
        entity.setContentType("application/json");
        httpPost.setEntity(entity);
        httpPost.setHeader("Accept", "application/json");
        //完成签名并执行请求
        CloseableHttpResponse response = httpClient.execute(httpPost);
        try {
            String bodyAsString = EntityUtils.toString(response.getEntity());   //响应体
            int statusCode = response.getStatusLine().getStatusCode();      //响应状态码
            if (statusCode == 200) { //处理成功
                log.info("成功,返回结果 = " + bodyAsString);
            } else if (statusCode == 204) { //处理成功，无返回Body
                log.info("成功，无返回结果");
            } else {
                log.info("native下单失败,响应码 = " + statusCode+ ",返回结果 = " + bodyAsString);
                return null;
            }

            HashMap<String,String> resultMap = gson.fromJson(bodyAsString, HashMap.class);

            //二维码
            String codeUrl = resultMap.get("code_url");



            return codeUrl;

        } finally {
            response.close();
        }
    }


    public String notifyPay(HttpServletRequest request) throws GeneralSecurityException, IOException {
        com.google.gson.Gson gson = new Gson();
        //处理通知参数
        String body = HttpUtils.readData(request);
        HashMap<String, Object> bodyMap = gson.fromJson(body, HashMap.class);
        log.info("支付通知的id ===> {}", bodyMap.get("id"));
        log.info("支付通知的完整数据 ===> {}", body);
        String id = (String) bodyMap.get("id");

        //签名的验证
        WechatPay2ValidatorForRequest wechatPay2ValidatorForRequest =
                new WechatPay2ValidatorForRequest(verifier, id, body);
        if (!wechatPay2ValidatorForRequest.validate(request)) {
            return null;
        }

        log.info("通知验签成功");

        // 处理订单
        //解密报文
        String plainText = decryptFromResource(bodyMap);
        return plainText;

    }

    //微信查单接口
    public String queryOrder(String orderNo) throws IOException {

        String url= String.format(WxApiEnum.QUERY_TRADE_API.getUrl(), orderNo);

        url = wxPayConfig.getDomain().concat(url).concat("?mchid=").concat(wxPayConfig.getMchId());

        HttpGet httpGet = new HttpGet(url);
        httpGet.setHeader("Accept","application/json");

        CloseableHttpResponse response = httpClient.execute(httpGet);

        try {
            String bodyAsString = EntityUtils.toString(response.getEntity());   //响应体
            int statusCode = response.getStatusLine().getStatusCode();      //响应状态码
            if(statusCode!=200&&statusCode!=204) {
                log.info("native下单失败,响应码 = " + statusCode+ ",返回结果 = " + bodyAsString);
                throw new IOException("request failed");
            }
            return bodyAsString;


        } finally {
            response.close();
        }

    }


    //关单接口
    public void closeOrder(String orderNo) throws IOException {


        String url= String.format(WxApiEnum.CLOSE_API.getUrl(), orderNo);
        url = wxPayConfig.getDomain().concat(url);
        HttpPost httpPost = new HttpPost(url);

        //组装json请求体
        Gson gson = new Gson();
        HashMap<String,String> paramsMap = new HashMap<>();
        paramsMap.put("mchid", wxPayConfig.getMchId());
        String jsonParams = gson.toJson(paramsMap);

        //请求参数设置到请求对象中
        StringEntity entity = new StringEntity(jsonParams,"utf-8");
        entity.setContentType("application/json");
        httpPost.setEntity(entity);
        httpPost.setHeader("Accept","application/json");

        //完成签名并执行请求
        CloseableHttpResponse response = httpClient.execute(httpPost);

        try {
            int statusCode = response.getStatusLine().getStatusCode();      //响应状态码
            if (statusCode!=200&&statusCode!=204){
                log.info("native下单失败,响应码 = " + statusCode);
                throw new IOException("request failed");
            }

        } finally {
            response.close();
        }

    }







    private String decryptFromResource(HashMap<String, Object> bodyMap) throws GeneralSecurityException {

        log.info("对称解密");

        //通知数据
        Map<String,String> resourceMap= (Map<String, String>) bodyMap.get("resource");
        //数据密文
        String ciphertext = resourceMap.get("ciphertext");
        //随机串
        String nonce = resourceMap.get("nonce");
        //附加数据
        String associatedData = resourceMap.get("associated_data");

        log.info("密文 = {}" ,ciphertext);
        AesUtil aesUtil = new AesUtil(wxPayConfig.getApiV3Key().getBytes());
        String plainText = aesUtil.decryptToString(associatedData.getBytes(StandardCharsets.UTF_8), nonce.getBytes(StandardCharsets.UTF_8), ciphertext);
        log.info("明文 = {}" ,plainText);
        return plainText;


    }
}
